Seven Lessons for Working with Language Models as a Programmer

Added at: July 10, 2025

(A distilled set of take-aways from Steve Krouse’s talk, “How to Work with Generative AI,” YouTube, May 2024)

1. From “Vibe Code” to Tight-Leash Engineering

  1. Vibe code is legacy code; generated code you don’t fully understand becomes a liability.
  2. Lack of shared theory, not age, makes code fragile and feared.
  3. Unchecked legacy snowballs into maintenance cost and technical debt.
  4. A tight-leash workflow—review, refactor, document—prevents legacy.

Rapid prototyping with an LLM feels magical—until you need to debug the maze it leaves. Review every patch, refactor immediately, and document intent to keep your codebase healthy.

2. Drop Line-Count Fetishism; Embrace a Theory-First Mind-Set

  1. Programming’s real product is a theory—a clear mental model—not lines of code.
  2. Senior engineers add value through deep understanding of invariants and edge cases.
  3. Code without a living theory becomes legacy instantly.
  4. Writing code is thinking in public; it refines ideas for humans first.
  5. Keep AI on a tight leash to preserve your mental model.
  6. Reading and understanding yield more leverage than writing new lines.
  7. Abstraction packages concepts into manageable chunks (~7 items).

Measure productivity by clarity of design, invest time in naming, small pure functions, and docstrings so your code documents its own intent.

3. Swap Agent Worship for Tool Amplification

  1. 2025’s “Year of the Agent” is a mirage—agents often sever your feedback loop.
  2. Delegation flags tooling gaps; build transparent, confirmatory tools instead.
  3. Treat LLMs as prosthetics—always visible and under your control.
  4. Agents turn you into a manager; tools empower you as a maker.
  5. Deploy interfaces—dashboards, inline explainers—not blank prompts.

Let the model handle plumbing while you stay in creative control: approve every step, test outputs, and maintain oversight.

4. Resist the Natural-Language Fantasy; Lean on Code Precision

  1. English-as-code is a 70-year false hope; ambiguity undermines reliability.
  2. Code offers compile-time guarantees and precise tokens for debuggability.
  3. Abstraction in code bundles behavior into human-sized chunks.
  4. Use prose for goals and constraints; implement in code for safety and refactor-friendliness.

Keep specs in prose and lock behavior into typed abstractions, tests, and contracts to catch errors early and maintain clarity.

5. Fight Latency & Context Loss with Instant Feedback Loops

  1. Latency kills flow; waiting breaks your mental stack.
  2. Slow feedback severs your understanding loop.
  3. Favor lower-latency helpers—even slightly dumber models that reply in 100 ms.
  4. Design inline completions and one-click refactors.

Match the cycle time to your thought rhythm—keep the handshake continuous with instant previews and on-the-spot explainers.

6. Trade Learned Helplessness for Principled Self-Reliance

  1. Model-of-the-day churn tempts you to blame tools, not gaps in understanding.
  2. Avoid the delegation spiral; interrogate results yourself.
  3. Reinforce your craft by anchoring in evergreen principles.

Use AI for provable leverage—regexes, test generation—but never outsource core thinking or foundational skills.

7. Stop Delegating the Fun; Keep the Brain in Play

  1. Joy optimizes cognition; keep engaging tasks for yourself.
  2. Delegate drudge—renames, boilerplate, imports—but not the delight.
  3. Intrinsic motivation compounds mastery over time.

Preserve intellectually rich work for humans; let AI mop up repetitive chores so you stay sharp and motivated.

Closing Thoughts

Language models are amplifiers, not replacements. Keep them transparent, keep your reasoning front-and-center, and you’ll ship fast software that remains maintainable and lovable long after version 1.0.